package com.hkj.configcenter.core.processor;

import com.hkj.configcenter.core.Context;
import com.hkj.configcenter.core.annotation.FieldValue;
import com.hkj.configcenter.core.model.FieldInfo;
import com.hkj.configcenter.core.utils.FieldUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class FieldConfigBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements PriorityOrdered {

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        try {

            if (!Context.isSwitchOn()) {
                return pvs;
            }

            List<Field> fields = getFields(bean.getClass());

            for (Field field : fields) {

                field.setAccessible(true);

                FieldValue annotation = field.getAnnotation(FieldValue.class);

                if (annotation != null) {
                    String paramName = annotation.name();
                    String pathValue = Context.getField_PathValue().get(paramName);
                    if (pathValue == null) {
                        if (StringUtils.isEmpty(annotation.defaultValue())) {
                            log.warn("【配置中心】【注意】没有字段配置，没有默认值==> {}", bean.getClass().getName() + "." + field.getName());
                        } else {
                            log.warn("【配置中心】【注意】没有字段【{}】取默认值==>{}", field.getName(), annotation.defaultValue());
                            FieldUtils.set(bean, field, annotation.defaultValue());
                        }
                    } else {
                        String[] path_value = pathValue.split(Context.SPLIT_FLAG);
                        FieldInfo fieldInfo = new FieldInfo(field, bean, path_value[0], path_value[1]);
                        List<FieldInfo> fieldInfos = Context.getFieldInfoCache().get(path_value[0]);
                        if (fieldInfos != null) {
                            fieldInfos.add(fieldInfo);
                        } else {
                            fieldInfos = new ArrayList<>();
                            fieldInfos.add(fieldInfo);
                            Context.getFieldInfoCache().put(path_value[0], fieldInfos);
                        }
                        FieldUtils.set(bean, field, path_value[1]);
                    }
                }

            }

        } catch (Throwable e) {
            log.error("【配置中心】 - FieldConfig 参数初始化失败", e);
            throw new IllegalArgumentException("【配置中心】 - FieldConfig 参数初始化失败");
        }

        return pvs;
    }

    private static List<Field> getFields(Class<?> clazz) {
        List<Field> list = new ArrayList<Field>();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            list.addAll(Arrays.asList(clazz.getDeclaredFields()));
        }
        return list;
    }

}